home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / FLOPPY.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  18KB  |  733 lines

  1. /* $Id: floppy.h,v 1.18 1999/03/21 10:51:38 davem Exp $
  2.  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  3.  *
  4.  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  6.  *
  7.  * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
  8.  */
  9.  
  10. #ifndef __ASM_SPARC64_FLOPPY_H
  11. #define __ASM_SPARC64_FLOPPY_H
  12.  
  13. #include <linux/config.h>
  14. #include <linux/init.h>
  15.  
  16. #include <asm/page.h>
  17. #include <asm/pgtable.h>
  18. #include <asm/system.h>
  19. #include <asm/idprom.h>
  20. #include <asm/oplib.h>
  21. #include <asm/auxio.h>
  22. #include <asm/sbus.h>
  23. #include <asm/irq.h>
  24.  
  25.  
  26. /*
  27.  * Define this to enable exchanging drive 0 and 1 if only drive 1 is
  28.  * probed on PCI machines.
  29.  */
  30. #undef PCI_FDC_SWAP_DRIVES
  31.  
  32.  
  33. /* References:
  34.  * 1) Netbsd Sun floppy driver.
  35.  * 2) NCR 82077 controller manual
  36.  * 3) Intel 82077 controller manual
  37.  */
  38. struct sun_flpy_controller {
  39.     volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
  40.     volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
  41.     volatile unsigned char dor_82077;     /* Digital Output reg. */
  42.     volatile unsigned char tapectl_82077; /* Tape Control reg */
  43.     volatile unsigned char status_82077;  /* Main Status Register. */
  44. #define drs_82077              status_82077   /* Digital Rate Select reg. */
  45.     volatile unsigned char data_82077;    /* Data fifo. */
  46.     volatile unsigned char ___unused;
  47.     volatile unsigned char dir_82077;     /* Digital Input reg. */
  48. #define dcr_82077              dir_82077      /* Config Control reg. */
  49. };
  50.  
  51. /* You'll only ever find one controller on an Ultra anyways. */
  52. static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
  53. volatile unsigned char *fdc_status;
  54. static struct linux_sbus_device *floppy_sdev = NULL;
  55.  
  56. struct sun_floppy_ops {
  57.     unsigned char    (*fd_inb) (unsigned long port);
  58.     void        (*fd_outb) (unsigned char value, unsigned long port);
  59.     void        (*fd_enable_dma) (void);
  60.     void        (*fd_disable_dma) (void);
  61.     void        (*fd_set_dma_mode) (int);
  62.     void        (*fd_set_dma_addr) (char *);
  63.     void        (*fd_set_dma_count) (int);
  64.     unsigned int    (*get_dma_residue) (void);
  65.     void        (*fd_enable_irq) (void);
  66.     void        (*fd_disable_irq) (void);
  67.     int        (*fd_request_irq) (void);
  68.     void        (*fd_free_irq) (void);
  69.     int        (*fd_eject) (int);
  70. };
  71.  
  72. static struct sun_floppy_ops sun_fdops;
  73.  
  74. #define fd_inb(port)              sun_fdops.fd_inb(port)
  75. #define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
  76. #define fd_enable_dma()           sun_fdops.fd_enable_dma()
  77. #define fd_disable_dma()          sun_fdops.fd_disable_dma()
  78. #define fd_request_dma()          (0) /* nothing... */
  79. #define fd_free_dma()             /* nothing... */
  80. #define fd_clear_dma_ff()         /* nothing... */
  81. #define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
  82. #define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
  83. #define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
  84. #define get_dma_residue(x)        sun_fdops.get_dma_residue()
  85. #define fd_enable_irq()           sun_fdops.fd_enable_irq()
  86. #define fd_disable_irq()          sun_fdops.fd_disable_irq()
  87. #define fd_cacheflush(addr, size) /* nothing... */
  88. #define fd_request_irq()          sun_fdops.fd_request_irq()
  89. #define fd_free_irq()             sun_fdops.fd_free_irq()
  90. #define fd_eject(drive)           sun_fdops.fd_eject(drive)
  91.  
  92. static int FLOPPY_MOTOR_MASK = 0x10;
  93.  
  94. /* Super paranoid... */
  95. #undef HAVE_DISABLE_HLT
  96.  
  97. static int sun_floppy_types[2] = { 0, 0 };
  98.  
  99. /* Here is where we catch the floppy driver trying to initialize,
  100.  * therefore this is where we call the PROM device tree probing
  101.  * routine etc. on the Sparc.
  102.  */
  103. #define FLOPPY0_TYPE        sun_floppy_init()
  104. #define FLOPPY1_TYPE        sun_floppy_types[1]
  105.  
  106. #define FDC1            ((unsigned long)sun_fdc)
  107. static int FDC2 =        -1;
  108.  
  109. #define N_FDC    1
  110. #define N_DRIVE  8
  111.  
  112. /* No 64k boundary crossing problems on the Sparc. */
  113. #define CROSS_64KB(a,s) (0)
  114.  
  115. static unsigned char sun_82077_fd_inb(unsigned long port)
  116. {
  117.     udelay(5);
  118.     switch(port & 7) {
  119.     default:
  120.         printk("floppy: Asked to read unknown port %lx\n", port);
  121.         panic("floppy: Port bolixed.");
  122.     case 4: /* FD_STATUS */
  123.         return sun_fdc->status_82077 & ~STATUS_DMA;
  124.     case 5: /* FD_DATA */
  125.         return sun_fdc->data_82077;
  126.     case 7: /* FD_DIR */
  127.         /* XXX: Is DCL on 0x80 in sun4m? */
  128.         return sun_fdc->dir_82077;
  129.     };
  130.     panic("sun_82072_fd_inb: How did I get here?");
  131. }
  132.  
  133. static void sun_82077_fd_outb(unsigned char value, unsigned long port)
  134. {
  135.     udelay(5);
  136.     switch(port & 7) {
  137.     default:
  138.         printk("floppy: Asked to write to unknown port %lx\n", port);
  139.         panic("floppy: Port bolixed.");
  140.     case 2: /* FD_DOR */
  141.         /* Happily, the 82077 has a real DOR register. */
  142.         sun_fdc->dor_82077 = value;
  143.         break;
  144.     case 5: /* FD_DATA */
  145.         sun_fdc->data_82077 = value;
  146.         break;
  147.     case 7: /* FD_DCR */
  148.         sun_fdc->dcr_82077 = value;
  149.         break;
  150.     case 4: /* FD_STATUS */
  151.         sun_fdc->status_82077 = value;
  152.         break;
  153.     };
  154.     return;
  155. }
  156.  
  157. /* For pseudo-dma (Sun floppy drives have no real DMA available to
  158.  * them so we must eat the data fifo bytes directly ourselves) we have
  159.  * three state variables.  doing_pdma tells our inline low-level
  160.  * assembly floppy interrupt entry point whether it should sit and eat
  161.  * bytes from the fifo or just transfer control up to the higher level
  162.  * floppy interrupt c-code.  I tried very hard but I could not get the
  163.  * pseudo-dma to work in c-code without getting many overruns and
  164.  * underruns.  If non-zero, doing_pdma encodes the direction of
  165.  * the transfer for debugging.  1=read 2=write
  166.  */
  167. char *pdma_vaddr;
  168. unsigned long pdma_size;
  169. volatile int doing_pdma = 0;
  170.  
  171. /* This is software state */
  172. char *pdma_base = 0;
  173. unsigned long pdma_areasize;
  174.  
  175. /* Common routines to all controller types on the Sparc. */
  176. static __inline__ void virtual_dma_init(void)
  177. {
  178.     /* nothing... */
  179. }
  180.  
  181. static void sun_fd_disable_dma(void)
  182. {
  183.     doing_pdma = 0;
  184.     if (pdma_base) {
  185.         mmu_unlockarea(pdma_base, pdma_areasize);
  186.         pdma_base = 0;
  187.     }
  188. }
  189.  
  190. static void sun_fd_set_dma_mode(int mode)
  191. {
  192.     switch(mode) {
  193.     case DMA_MODE_READ:
  194.         doing_pdma = 1;
  195.         break;
  196.     case DMA_MODE_WRITE:
  197.         doing_pdma = 2;
  198.         break;
  199.     default:
  200.         printk("Unknown dma mode %d\n", mode);
  201.         panic("floppy: Giving up...");
  202.     }
  203. }
  204.  
  205. static void sun_fd_set_dma_addr(char *buffer)
  206. {
  207.     pdma_vaddr = buffer;
  208. }
  209.  
  210. static void sun_fd_set_dma_count(int length)
  211. {
  212.     pdma_size = length;
  213. }
  214.  
  215. static void sun_fd_enable_dma(void)
  216. {
  217.     pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
  218.     pdma_base = pdma_vaddr;
  219.     pdma_areasize = pdma_size;
  220. }
  221.  
  222. /* Our low-level entry point in arch/sparc/kernel/entry.S */
  223. extern void floppy_hardint(int irq, void *unused, struct pt_regs *regs);
  224.  
  225. static int sun_fd_request_irq(void)
  226. {
  227.     static int once = 0;
  228.     int error;
  229.  
  230.     if(!once) {
  231.         once = 1;
  232.  
  233.         error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, 
  234.                     SA_INTERRUPT, "floppy", NULL);
  235.  
  236.         return ((error == 0) ? 0 : -1);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. static void sun_fd_enable_irq(void)
  242. {
  243. }
  244.  
  245. static void sun_fd_disable_irq(void)
  246. {
  247. }
  248.  
  249. static void sun_fd_free_irq(void)
  250. {
  251. }
  252.  
  253. static unsigned int sun_get_dma_residue(void)
  254. {
  255.     /* XXX This isn't really correct. XXX */
  256.     return 0;
  257. }
  258.  
  259. static int sun_fd_eject(int drive)
  260. {
  261.     set_dor(0x00, 0xff, 0x90);
  262.     udelay(500);
  263.     set_dor(0x00, 0x6f, 0x00);
  264.     udelay(500);
  265.     return 0;
  266. }
  267.  
  268. #ifdef CONFIG_PCI
  269. #include <asm/ebus.h>
  270. #include <asm/ns87303.h>
  271.  
  272. static struct linux_ebus_dma *sun_pci_fd_ebus_dma;
  273. static int sun_pci_broken_drive = -1;
  274.  
  275. extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
  276.  
  277. static unsigned char sun_pci_fd_inb(unsigned long port)
  278. {
  279.     return inb(port);
  280. }
  281.  
  282. static void sun_pci_fd_outb(unsigned char val, unsigned long port)
  283. {
  284.     outb(val, port);
  285. }
  286.  
  287. static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
  288. {
  289.     /*
  290.      * XXX: Due to SUN's broken floppy connector on AX and AXi
  291.      *      we need to turn on MOTOR_0 also, if the floppy is
  292.      *      jumpered to DS1 (like most PC floppies are). I hope
  293.      *      this does not hurt correct hardware like the AXmp.
  294.      *      (Eddie, Sep 12 1998).
  295.      */
  296.     if (port == ((unsigned long)sun_fdc) + 2) {
  297.         if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
  298.             val |= 0x10;
  299.         }
  300.     }
  301.     outb(val, port);
  302. }
  303.  
  304. #ifdef PCI_FDC_SWAP_DRIVES
  305. static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
  306. {
  307.     /*
  308.      * XXX: Due to SUN's broken floppy connector on AX and AXi
  309.      *      we need to turn on MOTOR_0 also, if the floppy is
  310.      *      jumpered to DS1 (like most PC floppies are). I hope
  311.      *      this does not hurt correct hardware like the AXmp.
  312.      *      (Eddie, Sep 12 1998).
  313.      */
  314.     if (port == ((unsigned long)sun_fdc) + 2) {
  315.         if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
  316.             val &= ~(0x03);
  317.             val |= 0x21;
  318.         }
  319.     }
  320.     outb(val, port);
  321. }
  322. #endif /* PCI_FDC_SWAP_DRIVES */
  323.  
  324. static void sun_pci_fd_reset_dma(void)
  325. {
  326.     unsigned int dcsr;
  327.  
  328.     writel(EBUS_DCSR_RESET, &sun_pci_fd_ebus_dma->dcsr);
  329.  
  330.     dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
  331.            EBUS_DCSR_EN_CNT | EBUS_DCSR_INT_EN;
  332.     writel(dcsr, (unsigned long)&sun_pci_fd_ebus_dma->dcsr);
  333. }
  334.  
  335. static void sun_pci_fd_enable_dma(void)
  336. {
  337.     unsigned int dcsr;
  338.  
  339.     dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  340.     dcsr |= EBUS_DCSR_EN_DMA;
  341.     writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
  342. }
  343.  
  344. static void sun_pci_fd_disable_dma(void)
  345. {
  346.     unsigned int dcsr;
  347.  
  348.     dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  349.     while (dcsr & EBUS_DCSR_DRAIN)
  350.         dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  351.     dcsr &= ~(EBUS_DCSR_EN_DMA);
  352.     if (dcsr & EBUS_DCSR_ERR_PEND)
  353.         sun_pci_fd_reset_dma();
  354.     writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
  355. }
  356.  
  357. static void sun_pci_fd_set_dma_mode(int mode)
  358. {
  359.     unsigned int dcsr;
  360.  
  361.     dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  362.     dcsr |= EBUS_DCSR_EN_CNT | EBUS_DCSR_TC;
  363.     /*
  364.      * For EBus WRITE means to system memory, which is
  365.      * READ for us.
  366.      */
  367.     if (mode == DMA_MODE_WRITE)
  368.         dcsr &= ~(EBUS_DCSR_WRITE);
  369.     else
  370.         dcsr |= EBUS_DCSR_WRITE;
  371.     writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
  372. }
  373.  
  374. static void sun_pci_fd_set_dma_count(int length)
  375. {
  376.     writel(length, &sun_pci_fd_ebus_dma->dbcr);
  377. }
  378.  
  379. static void sun_pci_fd_set_dma_addr(char *buffer)
  380. {
  381.     unsigned int addr = virt_to_bus(buffer);
  382.     writel(addr, &sun_pci_fd_ebus_dma->dacr);
  383. }
  384.  
  385. static unsigned int sun_pci_get_dma_residue(void)
  386. {
  387.     return readl(&sun_pci_fd_ebus_dma->dbcr);
  388. }
  389.  
  390. static void sun_pci_fd_enable_irq(void)
  391. {
  392.     unsigned int dcsr;
  393.  
  394.     dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  395.     dcsr |= EBUS_DCSR_INT_EN;
  396.     writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
  397. }
  398.  
  399. static void sun_pci_fd_disable_irq(void)
  400. {
  401.     unsigned int dcsr;
  402.  
  403.     dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
  404.     dcsr &= ~(EBUS_DCSR_INT_EN);
  405.     writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
  406. }
  407.  
  408. static int sun_pci_fd_request_irq(void)
  409. {
  410.     int err;
  411.  
  412.     err = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ,
  413.               "floppy", sun_fdc);
  414.     if (err)
  415.         return -1;
  416.     sun_pci_fd_enable_irq();
  417.     return 0;
  418. }
  419.  
  420. static void sun_pci_fd_free_irq(void)
  421. {
  422.     sun_pci_fd_disable_irq();
  423.     free_irq(FLOPPY_IRQ, sun_fdc);
  424. }
  425.  
  426. static int sun_pci_fd_eject(int drive)
  427. {
  428.     return -EINVAL;
  429. }
  430.  
  431.  
  432. /*
  433.  * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
  434.  * even if this is configured using DS1, thus looks like /dev/fd1 with
  435.  * the cabling used in Ultras.
  436.  */
  437. #define DOR    (port + 2)
  438. #define MSR    (port + 4)
  439. #define FIFO    (port + 5)
  440.  
  441. static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
  442.                     unsigned long reg)
  443. {
  444.     unsigned char status;
  445.     int timeout = 1000;
  446.  
  447.     while (!((status = inb(MSR)) & 0x80) && --timeout)
  448.         udelay(100);
  449.     outb(val, reg);
  450. }
  451.  
  452. static unsigned char sun_pci_fd_sensei(unsigned long port)
  453. {
  454.     unsigned char result[2] = { 0x70, 0x00 };
  455.     unsigned char status;
  456.     int i = 0;
  457.  
  458.     sun_pci_fd_out_byte(port, 0x08, FIFO);
  459.     do {
  460.         int timeout = 1000;
  461.  
  462.         while (!((status = inb(MSR)) & 0x80) && --timeout)
  463.             udelay(100);
  464.  
  465.         if (!timeout)
  466.             break;
  467.  
  468.         if ((status & 0xf0) == 0xd0)
  469.             result[i++] = inb(FIFO);
  470.         else
  471.             break;
  472.     } while (i < 2);
  473.  
  474.     return result[0];
  475. }
  476.  
  477. static void sun_pci_fd_reset(unsigned long port)
  478. {
  479.     unsigned char mask = 0x00;
  480.     unsigned char status;
  481.     int timeout = 10000;
  482.  
  483.     outb(0x80, MSR);
  484.     do {
  485.         status = sun_pci_fd_sensei(port);
  486.         if ((status & 0xc0) == 0xc0)
  487.             mask |= 1 << (status & 0x03);
  488.         else
  489.             udelay(100);
  490.     } while ((mask != 0x0f) && --timeout);
  491. }
  492.  
  493. static int sun_pci_fd_test_drive(unsigned long port, int drive)
  494. {
  495.     unsigned char status, data;
  496.     int timeout = 1000;
  497.     int ready;
  498.  
  499.     sun_pci_fd_reset(port);
  500.  
  501.     data = (0x10 << drive) | 0x0c | drive;
  502.     sun_pci_fd_out_byte(port, data, DOR);
  503.  
  504.     sun_pci_fd_out_byte(port, 0x07, FIFO);
  505.     sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
  506.  
  507.     do {
  508.         udelay(100);
  509.         status = sun_pci_fd_sensei(port);
  510.     } while (((status & 0xc0) == 0x80) && --timeout);
  511.  
  512.     if (!timeout)
  513.         ready = 0;
  514.     else
  515.         ready = (status & 0x10) ? 0 : 1;
  516.  
  517.     sun_pci_fd_reset(port);
  518.     return ready;
  519. }
  520. #undef FIFO
  521. #undef MSR
  522. #undef DOR
  523.  
  524. #endif /* CONFIG_PCI */
  525.  
  526. static struct linux_prom_registers fd_regs[2];
  527.  
  528. __initfunc(static unsigned long sun_floppy_init(void))
  529. {
  530.     char state[128];
  531.     int fd_node, num_regs;
  532.     struct linux_sbus *bus;
  533.     struct linux_sbus_device *sdev = NULL;
  534.     static int initialized = 0;
  535.  
  536.     if (initialized)
  537.         return sun_floppy_types[0];
  538.     initialized = 1;
  539.  
  540.     for_all_sbusdev (sdev, bus) {
  541.         if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
  542.             break;
  543.     }
  544.     if(sdev) {
  545.         floppy_sdev = sdev;
  546.         FLOPPY_IRQ = sdev->irqs[0];
  547.     } else {
  548. #ifdef CONFIG_PCI
  549.         struct linux_ebus *ebus;
  550.         struct linux_ebus_device *edev = 0;
  551.  
  552.         for_each_ebus(ebus) {
  553.             for_each_ebusdev(edev, ebus) {
  554.                 if (!strcmp(edev->prom_name, "fdthree"))
  555.                     goto ebus_done;
  556.             }
  557.         }
  558.     ebus_done:
  559.         if (!edev)
  560.             return 0;
  561.  
  562.         prom_getproperty(edev->prom_node, "status",
  563.                  state, sizeof(state));
  564.         if(!strncmp(state, "disabled", 8))
  565.             return 0;
  566.             
  567.         if (check_region(edev->base_address[1],
  568.                  sizeof(struct linux_ebus_dma))) {
  569.             printk("sun_floppy_init: can't get region at %016lx\n",
  570.                    edev->base_address[1]);
  571.             return 0;
  572.         }
  573.         request_region(edev->base_address[1],
  574.                    sizeof(struct linux_ebus_dma), "floppy DMA");
  575.  
  576.         sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
  577.         FLOPPY_IRQ = edev->irqs[0];
  578.  
  579.         sun_pci_fd_ebus_dma = (struct linux_ebus_dma *)
  580.                             edev->base_address[1];
  581.         sun_pci_fd_reset_dma();
  582.  
  583.         sun_fdops.fd_inb = sun_pci_fd_inb;
  584.         sun_fdops.fd_outb = sun_pci_fd_outb;
  585.  
  586.         use_virtual_dma = 0;
  587.         sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
  588.         sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
  589.         sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
  590.         sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
  591.         sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
  592.         sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
  593.  
  594.         sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq;
  595.         sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq;
  596.         sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
  597.         sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
  598.  
  599.         sun_fdops.fd_eject = sun_pci_fd_eject;
  600.  
  601.             fdc_status = &sun_fdc->status_82077;
  602.         FLOPPY_MOTOR_MASK = 0xf0;
  603.  
  604.         /*
  605.          * XXX: Find out on which machines this is really needed.
  606.          */
  607.         if (1) {
  608.             sun_pci_broken_drive = 1;
  609.             sun_fdops.fd_outb = sun_pci_fd_broken_outb;
  610.         }
  611.  
  612.         allowed_drive_mask = 0;
  613.         if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
  614.             sun_floppy_types[0] = 4;
  615.         if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
  616.             sun_floppy_types[1] = 4;
  617.  
  618. #ifdef PCI_FDC_SWAP_DRIVES
  619.         /*
  620.          * If only Floppy 1 is present, swap drives.
  621.          */
  622.         if (!sun_floppy_types[0] && sun_floppy_types[1]) {
  623.             unsigned long config = 0;
  624.             unsigned char tmp;
  625.  
  626.             for_each_ebus(ebus) {
  627.                 for_each_ebusdev(edev, ebus) {
  628.                     if (!strcmp(edev->prom_name, "ecpp")) {
  629.                         config = edev->base_address[1];
  630.                         goto config_done;
  631.                     }
  632.                 }
  633.             }
  634.         config_done:
  635.  
  636.             /*
  637.              * Sanity check, is this really the NS87303?
  638.              */
  639.             switch (config & 0x3ff) {
  640.             case 0x02e:
  641.             case 0x15c:
  642.             case 0x26e:
  643.             case 0x398:
  644.                 break;
  645.             default:
  646.                 config = 0;
  647.             }
  648.  
  649.             if (!config)
  650.                 return sun_floppy_types[0];
  651.  
  652.             /*
  653.              * Set the drive exchange bit in FCR on NS87303,
  654.              * make shure other bits are sane before doing so.
  655.              */
  656.             tmp = ns87303_readb(config, FER);
  657.             tmp &= ~(FER_EDM);
  658.             ns87303_writeb(config, FER, tmp);
  659.             tmp = ns87303_readb(config, ASC);
  660.             tmp &= ~(ASC_DRV2_SEL);
  661.             ns87303_writeb(config, ASC, tmp);
  662.             tmp = ns87303_readb(config, FCR);
  663.             tmp |= FCR_LDE;
  664.             ns87303_writeb(config, FCR, tmp);
  665.  
  666.             tmp = sun_floppy_types[0];
  667.             sun_floppy_types[0] = sun_floppy_types[1];
  668.             sun_floppy_types[1] = tmp;
  669.  
  670.             if (sun_pci_broken_drive != -1) {
  671.                 sun_pci_broken_drive = 1 - sun_pci_broken_drive;
  672.                 sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
  673.             }
  674.         }
  675. #endif /* PCI_FDC_SWAP_DRIVES */
  676.  
  677.         return sun_floppy_types[0];
  678. #else
  679.         return 0;
  680. #endif
  681.     }
  682.     fd_node = sdev->prom_node;
  683.     prom_getproperty(fd_node, "status", state, sizeof(state));
  684.     if(!strncmp(state, "disabled", 8))
  685.         return 0;
  686.     num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs,
  687.                     sizeof(fd_regs));
  688.     num_regs = (num_regs / sizeof(fd_regs[0]));
  689.     prom_apply_sbus_ranges(sdev->my_bus, fd_regs, num_regs, sdev);
  690.     /*
  691.      * We cannot do sparc_alloc_io here: it does request_region,
  692.      * which the generic floppy driver tries to do once again.
  693.      */
  694.     sun_fdc = (struct sun_flpy_controller *)
  695.                 (PAGE_OFFSET + fd_regs[0].phys_addr + 
  696.                  (((unsigned long)fd_regs[0].which_io) << 32));
  697.  
  698.     /* Last minute sanity check... */
  699.     if(sun_fdc->status1_82077 == 0xff) {
  700.         sun_fdc = (struct sun_flpy_controller *)-1;
  701.         return 0;
  702.     }
  703.  
  704.         sun_fdops.fd_inb = sun_82077_fd_inb;
  705.         sun_fdops.fd_outb = sun_82077_fd_outb;
  706.  
  707.     can_use_virtual_dma = use_virtual_dma = 1;
  708.     sun_fdops.fd_enable_dma = sun_fd_enable_dma;
  709.     sun_fdops.fd_disable_dma = sun_fd_disable_dma;
  710.     sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
  711.     sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
  712.     sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
  713.     sun_fdops.get_dma_residue = sun_get_dma_residue;
  714.  
  715.     sun_fdops.fd_enable_irq = sun_fd_enable_irq;
  716.     sun_fdops.fd_disable_irq = sun_fd_disable_irq;
  717.     sun_fdops.fd_request_irq = sun_fd_request_irq;
  718.     sun_fdops.fd_free_irq = sun_fd_free_irq;
  719.  
  720.     sun_fdops.fd_eject = sun_fd_eject;
  721.  
  722.         fdc_status = &sun_fdc->status_82077;
  723.  
  724.     /* Success... */
  725.     allowed_drive_mask = 0x01;
  726.     sun_floppy_types[0] = 4;
  727.     sun_floppy_types[1] = 0;
  728.  
  729.     return sun_floppy_types[0];
  730. }
  731.  
  732. #endif /* !(__ASM_SPARC64_FLOPPY_H) */
  733.